package gu.doc;

import java.io.File;
import java.util.List;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.RootDoc;

/**
 * 读取指定java源文件的javadoc信息
 * @author guyadong
 *
 */
public class JavadocReader {
	private static RootDoc root = null;
	public static  class Doclet {
	    public static boolean start(RootDoc root) {
	    	JavadocReader.root = root;
	        return true;
	    }
	}
	public static void show(){
		if(null == root){
			return ;
		}
        ClassDoc[] classes = root.classes();
        for (int i = 0; i < classes.length; ++i) {
        	new ExtClassDoc(classes[i]).output(System.out);
        }
	}
	/**
	 * 解析指定的java源文件返回javadoc对象 {@link RootDoc}<br>
	 * 参见 <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/standard-doclet.html#runningprogrammatically">Running the Standard Doclet Programmatically</a>
	 * @param source a java source file or package name
	 * @param classpath value for  '-classpath',{@code source}的class位置,可为{@code null},如果不提供,无法获取到完整的注释信息(比如annotation)
	 * @param sourcepath value for '-sourcepath'
	 * @return
	 */
	public synchronized static RootDoc readDocs(String source, String classpath,String sourcepath) {
		if(Strings.isNullOrEmpty(source)){
			return null;
		}
		Preconditions.checkArgument(!Strings.isNullOrEmpty(source), "source is null");
		List<String> args = Lists.newArrayList("-doclet", 
				Doclet.class.getName(), "-quiet","-Xmaxerrs","1","-Xmaxwarns","1","-encoding","utf-8");
		if(!Strings.isNullOrEmpty(classpath)){
			args.add("-classpath");
			args.add(classpath);
		}
		if(!Strings.isNullOrEmpty(sourcepath)){
			args.add("-sourcepath");
			args.add(sourcepath);
		}
		args.add(source);
		int returnCode = com.sun.tools.javadoc.Main.execute(JavadocReader.class.getClassLoader(),args.toArray(new String[args.size()]));
		if(0 != returnCode){
			throw new IllegalStateException();
		}
		return root;
	}
	public synchronized static ExtClassDoc read(String source, String classpath,String sourcepath) {
		return new ExtClassDoc(readDocs(source, classpath, sourcepath).classes()[0]);
	}
	/** @see #read(String, String) */
	public static ExtClassDoc read(String source) {
		return read(source,(String)null);
	}
	public static ExtClassDoc read(String source, List<String> classpath) {
		return read(source,null == classpath?null:Joiner.on(File.pathSeparator).skipNulls().join(classpath));
	}
	public static ExtClassDoc read(String source, String[] classpath) {
		return read(source,null == classpath?null:Joiner.on(File.pathSeparator).skipNulls().join(classpath));
	}
	public synchronized static ExtClassDoc read(String source, String classpath) {
		return read(source,classpath,null);
	}
	public static ExtClassDoc read(String source, List<String> classpath,List<String> sourcepath) {
		return read(source,
				null == classpath ? null : Joiner.on(File.pathSeparator).skipNulls().join(classpath),
				null == sourcepath ? null : Joiner.on(",").skipNulls().join(sourcepath));
	}
	public static ExtClassDoc read(String source, String[] classpath,String[] sourcepath) {
		return read(source,
				null == classpath ? null : Joiner.on(File.pathSeparator).skipNulls().join(classpath),
				null == sourcepath ? null : Joiner.on(",").skipNulls().join(sourcepath));
	}
}
